{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "MhoQ0WE77laV"
   },
   "source": [
    "##### Copyright 2018 The TensorFlow Authors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "_ckMIh7O7s6D"
   },
   "outputs": [],
   "source": [
    "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "vasWnqRgy1H4"
   },
   "outputs": [],
   "source": [
    "#@title MIT License\n",
    "#\n",
    "# Copyright (c) 2017 François Chollet\n",
    "#\n",
    "# Permission is hereby granted, free of charge, to any person obtaining a\n",
    "# copy of this software and associated documentation files (the \"Software\"),\n",
    "# to deal in the Software without restriction, including without limitation\n",
    "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
    "# and/or sell copies of the Software, and to permit persons to whom the\n",
    "# Software is furnished to do so, subject to the following conditions:\n",
    "#\n",
    "# The above copyright notice and this permission notice shall be included in\n",
    "# all copies or substantial portions of the Software.\n",
    "#\n",
    "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
    "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
    "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
    "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
    "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
    "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
    "# DEALINGS IN THE SOFTWARE."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "jYysdyb-CaWM"
   },
   "source": [
    "# Обучи свою первую нейросеть: простой классификатор"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "S5Uhzt6vVIB2"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/basic_classification\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Читай на TensorFlow.org</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ru/tutorials/keras/basic_classification.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Запусти в Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ru/tutorials/keras/basic_classification.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Изучай код на GitHub</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FbVhjPpzn6BM"
   },
   "source": [
    "Это пошаговое руководство поможет тебе обучить свою первую нейросеть, которая будет классифицировать картинки предметов одежды.\n",
    "\n",
    "Все в порядке если какие-то нюансы будет непонятны тебе в первый раз: это быстрая, ознакомительная программа по TensorFlow, которая показывает и объясняет новые детали по мере их появления.\n",
    "\n",
    "В уроке используется [tf.keras](https://www.tensorflow.org/guide/keras), высокоуровневый Keras API для построения и обучения моделей в TensorFlow."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "dzLKpmZICaWN"
   },
   "outputs": [],
   "source": [
    "# Импортируем TensorFlow и tf.keras\n",
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "\n",
    "# А также добавим вспомогательные библиотеки для вычислений и вывода данных на экран\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "yR0EdgrLCaWR"
   },
   "source": [
    "## Загружаем Fashion MNIST датасет"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DLdCchMdCaWQ"
   },
   "source": [
    "Мы будем использовать [Fashion MNIST](https://github.com/zalandoresearch/fashion-mnist) датасет, который состоит из 70,000 черно-белых изображений в 10 категориях. На каждом изображении по одному предмету одежды в низком разрешении (28 на 28 пикселей):\n",
    "\n",
    "<table>\n",
    "  <tr><td>\n",
    "    <img src=\"https://tensorflow.org/images/fashion-mnist-sprite.png\"\n",
    "         alt=\"Fashion MNIST sprite\"  width=\"600\">\n",
    "  </td></tr>\n",
    "  <tr><td align=\"center\">\n",
    "    <b>Рис. 1.</b> <a href=\"https://github.com/zalandoresearch/fashion-mnist\">Образцы Fashion-MNIST</a> (Zalando, лицензия MIT).<br/>&nbsp;\n",
    "  </td></tr>\n",
    "</table>\n",
    "\n",
    "Fashion MNIST составлялся как замена классическому [MNIST](http://yann.lecun.com/exdb/mnist/) датасету, который часто используют на первых уроках в программах по компьютерному зрению - своебразный \"Hello, World\" в мире машинного обучения. Классический датасет MNIST состоит из изображений рукописных чисел (0, 1, 2 и так далее) в точно таком же формате, как и предметы одежды, которыми мы будем пользоваться сегодня.\n",
    "\n",
    "Для разнообразия сегодня мы будем ипользовать Fashion MNIST, а также потому, что он представляет большую сложность в сравнении с MNIST. Оба датасета относительно малы, и нужны для проверки правильно ли работает алгоритм или нет. Их удобно использовать как отправные точки для тестирования и отладки кода.\n",
    "\n",
    "Чтобы обучить модель мы потренируем нейросеть на 60,000 изображений, а также загрузим еще 10,000 чтобы проверить, насколько правильно нейросеть обучилась предсказывать их класс. Ты можешь загрузить Fashion MNIST прямо в TensorFlow, просто сделай импорт и загрузи картинки:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "7MqDQO0KCaWS"
   },
   "outputs": [],
   "source": [
    "fashion_mnist = keras.datasets.fashion_mnist\n",
    "\n",
    "(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "t9FDsUlxCaWW"
   },
   "source": [
    "Загрузка датасета возвращает 4 массива NumPy:\n",
    "\n",
    "* Массивы `train_images` и `train_labels` являются *тренировочным сетом* — данными, на которых модель будет обучаться\n",
    "* Модель тестируется на *проверочном сете* - против массивов `test_images` и `test_labels`\n",
    "\n",
    "Изображения являются 28х28 массивами NumPy, где значение пикселей варьируется от 0 до 255. В столбике *Label* (далее - классы) содержится массив целых чисел от 0 до 9. Они соответствуют классу одежды, которые изображены на картинках:\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <th>Label</th>\n",
    "    <th>Class</th> \n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td>0</td>\n",
    "    <td>T-shirt/top</td> \n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td>1</td>\n",
    "    <td>Trouser</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>2</td>\n",
    "    <td>Pullover</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>3</td>\n",
    "    <td>Dress</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>4</td>\n",
    "    <td>Coat</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>5</td>\n",
    "    <td>Sandal</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>6</td>\n",
    "    <td>Shirt</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>7</td>\n",
    "    <td>Sneaker</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>8</td>\n",
    "    <td>Bag</td> \n",
    "  </tr>\n",
    "    <tr>\n",
    "    <td>9</td>\n",
    "    <td>Ankle boot</td> \n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Каждому изображению соответствует всего один класс одежды. Так как *названия классов* не включены в датасет, мы сохраним их здесь, чтобы позже использовать их для вывода изображений с указанием категорий одежды:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "IjnLH5S2CaWx"
   },
   "outputs": [],
   "source": [
    "class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', \n",
    "               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Brm0b_KACaWX"
   },
   "source": [
    "## Изучаем данные\n",
    "\n",
    "Давай посмотрим на формат данных в датасете прежде, чем начнем тренировать модель. При помощи *shape* мы видим, что датасет состоит из 60,000 изображений размером 28 х 28 пикселей: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "zW5k_xz1CaWX"
   },
   "outputs": [],
   "source": [
    "train_images.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "cIAcvQqMCaWf"
   },
   "source": [
    "Также мы видим, что в тренировочном сете всего 60,000 меток, по одной на каждое изображение:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "TRFYHB2mCaWb"
   },
   "outputs": [],
   "source": [
    "len(train_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "YSlYxFuRCaWk"
   },
   "source": [
    "Каждая метка - это целое число от 0 до 9:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "XKnCTHz4CaWg"
   },
   "outputs": [],
   "source": [
    "train_labels"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "TMPI88iZpO2T"
   },
   "source": [
    "Тренировочный сет содержит 10,000 изображений, каждое - также 28 на 28 пикселей:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "2KFnYlcwCaWl"
   },
   "outputs": [],
   "source": [
    "test_images.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "rd0A0Iu0CaWq"
   },
   "source": [
    "А в тренировочном сете - ровно 10,000 меток:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "iJmPr5-ACaWn"
   },
   "outputs": [],
   "source": [
    "len(test_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ES6uQoLKCaWr"
   },
   "source": [
    "## Подготовка данных к обучению модели\n",
    "\n",
    "Все данные должны быть подготовлены и обработаны одинаково перед обучением нейросети. Если мы посмотрим на первое изображение в тренировочном сете мы увидим, что значение пикселей находится в диапазоне от о до 255:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "m4VEw8Ud9Quh"
   },
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "plt.imshow(train_images[0])\n",
    "plt.colorbar()\n",
    "plt.grid(False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Wz7l27Lz9S1P"
   },
   "source": [
    "Мы должны определить эти значения в диапазоне от 0 до 1 прежде, чем обучать нейронную сеть. Для этого переведем тип данных изображений из целых в числа с плавающей запятой, и разделим на 255.\n",
    "\n",
    "Важно, чтобы и тренировочный, и проверочный сет были подготовлены одинаково."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "3jCZdQNNCaWv"
   },
   "source": [
    "Так будет выглядеть функция чтобы подготовить все изображения:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "bW5WzIPlCaWv"
   },
   "outputs": [],
   "source": [
    "train_images = train_images / 255.0\n",
    "\n",
    "test_images = test_images / 255.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Ee638AlnCaWz"
   },
   "source": [
    "Выведем на экран 25 изображений из тренировочного сета и укажем класс (Label) под каждым. Таким образом мы убедимся, что наши данные в правильном формате и готовы для построения и обучения нейросети."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "oZTImqg_CaW1"
   },
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10,10))\n",
    "for i in range(25):\n",
    "    plt.subplot(5,5,i+1)\n",
    "    plt.xticks([])\n",
    "    plt.yticks([])\n",
    "    plt.grid(False)\n",
    "    plt.imshow(train_images[i], cmap=plt.cm.binary)\n",
    "    plt.xlabel(class_names[train_labels[i]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "59veuiEZCaW4"
   },
   "source": [
    "## Строим модель\n",
    "\n",
    "Построение модели нейронной сети требует правильной конфигурации каждого слоя, и последующей компиляции."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Gxg1XGm0eOBy"
   },
   "source": [
    "### Создаем слои\n",
    "\n",
    "Составными частями нейросетей являются *слои*. Они извлекают точные представления из данных, на которых их обучают. И конечно же будем надеяться что в конечном итоге они извлекут что-то полезное для наших практических задач.\n",
    "\n",
    "Большинство моделей глубокого обучения состоят из простых слоев в цепочке. Большинство же слоев, таких как например `tf.keras.layers.Dense`, имеют параметры которые используются в процессе тренировки:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "9ODch-OFCaW4"
   },
   "outputs": [],
   "source": [
    "model = keras.Sequential([\n",
    "    keras.layers.Flatten(input_shape=(28, 28)),\n",
    "    keras.layers.Dense(128, activation=tf.nn.relu),\n",
    "    keras.layers.Dense(10, activation=tf.nn.softmax)\n",
    "])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "gut8A_7rCaW6"
   },
   "source": [
    "Первый слой в нашей нейросети - `tf.keras.layers.Flatten` (flatten, пер. \"Выравнивать\"), будеn трансформировать изображения из 2D-массива (28 x 28 пикселей), в 1D-массив из 28 * 28 = 784 пикселей. Представь, что в этом слое мы как будто разбираем ряды сложенных пикселей изображения и выкладываем их в ряд. Этот слой не имеет никаких параметров для обучения; он просто преобразует формат данных.\n",
    "\n",
    "После того, как мы разложили все пиксели, нейросеть будет состоять из двух Dense (пер. \"Плотный\") `tf.keras.layers.Dense` слоев. Это так называемые полносвязные слои. Первый `Dense` слой состоит из 128 узлов, или нейронов. Второй и последний *softmax* слой — возвращает массив с вероятностной шкалой которая должна равняться 1. Каждый нейрон содержит оценку, которая указывает вероятность принадлежности изображения к одному из 10 классов.\n",
    "\n",
    "### Компилируем модель\n",
    "\n",
    "Прежде чем модель будет готова для обучения, нам нужно указать еще несколько параметров. Их необходимо добавить в блоке *compile*:\n",
    "\n",
    "* *Loss function* (пер. \"Функция потерь\") — измеряет точность модели во время обучения. Мы хотим минимизировать значение этой функции, чтобы \\\"направить\\\" модель в нужном направлении\n",
    "\n",
    "* *Optimizer* — показывает каким образом обновляется модель на основе входных данных и функции потерь\n",
    "\n",
    "* *Metrics* — показывают шаги тренировки и тестирования модели. В нашем примере мы будем использовать *accuracy*, т.е. процент изображений, которые были классифицированы правильно"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Lhan11blCaW7"
   },
   "outputs": [],
   "source": [
    "model.compile(optimizer=tf.train.AdamOptimizer(), \n",
    "              loss='sparse_categorical_crossentropy',\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "qKF6uW-BCaW-"
   },
   "source": [
    "## Обучение модели\n",
    "\n",
    "Обучение модели нейронной сети требует выполнения следующих шагов:\n",
    "\n",
    "1. Загрузить тренировочные данные в модель, в нашем случае - массивами `train_images` и `train_labels`\n",
    "2. Модель учится ассоциировать изображения с правильными классами\n",
    "3. Мы запрашиваем модель предсказать классы одежды из тренировочного сета `test_images`. Мы проверяем, соответствуют ли предсказанные классы меткам из массива `test_labels`. \n",
    "\n",
    "Чтобы начать обучение, укажи метод `model.fit` (fit, пер. \"Приспосабливать\", \"Вмещать\") - модель начнет обучаться на тренировочных данных:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "xvwvpA64CaW_"
   },
   "outputs": [],
   "source": [
    "model.fit(train_images, train_labels, epochs=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "W3ZVOhugCaXA"
   },
   "source": [
    "Пока модель учится, мы видим показатели потери (*loss*) и точности (*acc*). В итоге модель достигает точности приблизительно 0.88 (88%), обучаясь на тренировочном сете."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "oEw4bZgGCaXB"
   },
   "source": [
    "## Рассчитываем точность\n",
    "\n",
    "Далее, сравним какую точность полученная нами модель покажет на проверчном датасете:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "VflXLEeECaXC"
   },
   "outputs": [],
   "source": [
    "test_loss, test_acc = model.evaluate(test_images, test_labels)\n",
    "\n",
    "print('Test accuracy:', test_acc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "yWfgsmVXCaXG"
   },
   "source": [
    "Полученная на проверчном сете точность оказалось немного ниже, чем на тренировочном сете. Этот разрыв между точностью на тренировке и тесте является примером *overfitting* (пер. \"Переобучение\"). Переобучение как правило возникает когда модель машинного обучения показывает результат хуже на новых данных, чем на тех, на которой она обучалась."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "xsoS7CPDCaXH"
   },
   "source": [
    "## Получим предсказания\n",
    "\n",
    "Теперь, когда модель обучена, мы можем попробовать получить предсказания классов одежды на основе новых изображений:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Gl91RPhdCaXI"
   },
   "outputs": [],
   "source": [
    "predictions = model.predict(test_images)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "x9Kk1voUCaXJ"
   },
   "source": [
    "Здесь полученная модель будет предсказывать класс одежды для каждого изображения в проверчном датасете. \n",
    "\n",
    "Давай посмотрим на первое классификацию:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "3DmJEUinCaXK"
   },
   "outputs": [],
   "source": [
    "predictions[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "-hw1hgeSCaXN"
   },
   "source": [
    "Предсказание класса представляет из себя массив из 10 чисел. Они описывают \"уверенность\" (*confidence*) соответствия изображения одному из 10 разных классов одежды. При помощи `np.argmax` мы можем увидеть самую высокую уверенность:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "qsqenuPnCaXO"
   },
   "outputs": [],
   "source": [
    "np.argmax(predictions[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "E51yS7iCCaXO"
   },
   "source": [
    "Обученная модель думает, что на первой картинке изображен бамшмак (ankle boot), или `class_names[9]`. И мы можем проверить, правильно ли это или нет:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Sd7Pgsu6CaXP"
   },
   "outputs": [],
   "source": [
    "test_labels[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ygh2yYC972ne"
   },
   "source": [
    "Давай создадим функцию для быстрого построения диаграмм и посмотрим, как выглядят предсказания:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "DvYmmrpIy6Y1"
   },
   "outputs": [],
   "source": [
    "def plot_image(i, predictions_array, true_label, img):\n",
    "  predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]\n",
    "  plt.grid(False)\n",
    "  plt.xticks([])\n",
    "  plt.yticks([])\n",
    "  \n",
    "  plt.imshow(img, cmap=plt.cm.binary)\n",
    "\n",
    "  predicted_label = np.argmax(predictions_array)\n",
    "  if predicted_label == true_label:\n",
    "    color = 'blue'\n",
    "  else:\n",
    "    color = 'red'\n",
    "  \n",
    "  plt.xlabel(\"{} {:2.0f}% ({})\".format(class_names[predicted_label],\n",
    "                                100*np.max(predictions_array),\n",
    "                                class_names[true_label]),\n",
    "                                color=color)\n",
    "\n",
    "def plot_value_array(i, predictions_array, true_label):\n",
    "  predictions_array, true_label = predictions_array[i], true_label[i]\n",
    "  plt.grid(False)\n",
    "  plt.xticks([])\n",
    "  plt.yticks([])\n",
    "  thisplot = plt.bar(range(10), predictions_array, color=\"#777777\")\n",
    "  plt.ylim([0, 1]) \n",
    "  predicted_label = np.argmax(predictions_array)\n",
    " \n",
    "  thisplot[predicted_label].set_color('red')\n",
    "  thisplot[true_label].set_color('blue')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "d4Ov9OFDMmOD"
   },
   "source": [
    "Теперь посмотрим на самое первое изображение (0), предсказание класса, используя нашу новую функцию:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "HV5jw-5HwSmO"
   },
   "outputs": [],
   "source": [
    "i = 0\n",
    "plt.figure(figsize=(6,3))\n",
    "plt.subplot(1,2,1)\n",
    "plot_image(i, predictions, test_labels, test_images)\n",
    "plt.subplot(1,2,2)\n",
    "plot_value_array(i, predictions,  test_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Для сравнения посмотрим на другое изображение (12):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Ko-uzOufSCSe"
   },
   "outputs": [],
   "source": [
    "i = 12\n",
    "plt.figure(figsize=(6,3))\n",
    "plt.subplot(1,2,1)\n",
    "plot_image(i, predictions, test_labels, test_images)\n",
    "plt.subplot(1,2,2)\n",
    "plot_value_array(i, predictions,  test_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "kgdvGD52CaXR"
   },
   "source": [
    "Теперь давай отобразим несколько изображений и их предсказанные классы:\n",
    "\n",
    "1. Правильные предсказания будут отмечены синим, неправильные - красным\n",
    "2. Также мы укажем процент правильности предсказания метки изображения\n",
    "\n",
    "Обрати внимание:\n",
    "\n",
    "Предсказания могут быть неправильными, даже если модель уверена что все верно!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "hQlnbqaw2Qu_"
   },
   "outputs": [],
   "source": [
    "# Plot the first X test images, their predicted label, and the true label\n",
    "# Color correct predictions in blue, incorrect predictions in red\n",
    "num_rows = 5\n",
    "num_cols = 3\n",
    "num_images = num_rows*num_cols\n",
    "plt.figure(figsize=(2*2*num_cols, 2*num_rows))\n",
    "for i in range(num_images):\n",
    "  plt.subplot(num_rows, 2*num_cols, 2*i+1)\n",
    "  plot_image(i, predictions, test_labels, test_images)\n",
    "  plt.subplot(num_rows, 2*num_cols, 2*i+2)\n",
    "  plot_value_array(i, predictions, test_labels)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "R32zteKHCaXT"
   },
   "source": [
    "Наконец, мы используем обученную модель сделать предсказание класса на одном изображении:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "yRJ7JU7JCaXT"
   },
   "outputs": [],
   "source": [
    "# Берем одну картинку из проверочного сета\n",
    "img = test_images[0]\n",
    "\n",
    "print(img.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vz3bVp21CaXV"
   },
   "source": [
    "Модели `tf.keras` оптимизированы делать предсказания на *batch* (пер. \"Пакетах данных\"), или на множестве примеров сразу. Таким образом, даже если мы используем всего 1 картинку, нам все равно необходимо добавить ее в список:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "lDFh5yF_CaXW"
   },
   "outputs": [],
   "source": [
    "# Добавляем изображение в наш пакет данных\n",
    "img = (np.expand_dims(img,0))\n",
    "\n",
    "print(img.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "EQ5wLTkcCaXY"
   },
   "source": [
    "И предсказываем класс этого изображения:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "o_rzNSdrCaXY"
   },
   "outputs": [],
   "source": [
    "predictions_single = model.predict(img)\n",
    "\n",
    "print(predictions_single)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Выводим на экран диаграмму:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "6Ai-cpLjO-3A"
   },
   "outputs": [],
   "source": [
    "plot_value_array(0, predictions_single, test_labels)\n",
    "_ = plt.xticks(range(10), class_names, rotation=45)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "cU1Y2OAMCaXb"
   },
   "source": [
    "Метод `model.predict` возвращает нам список списков, один для каждой картинки в пакете данных.\n",
    "\n",
    "При помощи `np.argmax` давай оставим предсказание с максимальной вероятностью для нашей картинки:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "2tRmdq_8CaXb"
   },
   "outputs": [],
   "source": [
    "np.argmax(predictions_single[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "YFc2HbEVCaXd"
   },
   "source": [
    "И, как и в первый раз, модель предсказывает нам класс 9 - это башмак!"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "basic_classification.ipynb",
   "private_outputs": true,
   "provenance": [],
   "toc_visible": true,
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
